#include"SList.h"

void SLTPrint(SLTNode* phead) //phear指向链表的第一个结点的地址
{
    SLTNode* pcur = phead;  //pcur指向的是第一个结点的指针
    while (pcur)
    {
        printf("%d->", pcur->data);
        pcur = pcur->next;
    }
    printf("NULL\n");
}


//定义一个申请新结点的函数
SLTNode* SLTBuyNode(SLTDataType x)
{
    SLTNode* node = (SLTNode*)malloc(sizeof(SLTNode));
    if (node == NULL)
    {
        perror("malloc fail");
        exit(1);
    }
    node->data = x;
    node->next = NULL;

    return node;
}



//尾部插入函数         //二级指针
void SLPushBack(SLTNode** pphead, SLTDataType x)
{
    assert(pphead);


    //pphead接收的是&plist（plist就是指向第一个节点的指针）
    // *pphead=plist（解引用pphead）
    //申请新结点
    SLTNode* newnode = SLTBuyNode(x);
    //用链表尾结点指向定义的新结点从而来插入数据
    //找尾结点
    SLTNode* pcur = *pphead; //此时pcur和phear都为NULL
    if (*pphead == NULL)
    {
        *pphead = newnode;
    }
    else
    {
        while (pcur->next)
        {
            pcur = pcur->next;//pcur下一个指向地址给当前pcur指针；
        }
        //连接pucr和newnode
        pcur->next = newnode;
    }
}



//头部插入函数
void SLPushFront(SLTNode** pphead, SLTDataType x)
{
    assert(pphead);
    SLTNode* newnode = SLTBuyNode(x);

    //让新结点newnode的next指针 指向头结点*pphead
    newnode->next = *pphead;
    *pphead = newnode;
}




//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x) 
{
    assert(pphead);
    assert(pos);

    if (pos == *pphead)
    {
        SLPushFront(pphead, x);
    }
    else
    {
        SLTNode* newnode = SLTBuyNode(x);
        SLTNode* prev = *pphead; //找pos的前一个结点prev（需要从头开始遍历）
        while (prev->next != pos)
        {
            prev = prev->next;//这里是继续循环的操作，prev要一个一个往下找
        }
        //以上操作已经找到了prev和pos，现在需要在二者中间插入newnode
        newnode->next = pos->next;
        prev->next = newnode;

    }
}




//在指定位置之后插入数据 
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{
     //要先让新插入的结点newnode指向指定位置的下一个结点pos->next，再让pos->next指针指向newnode
    assert(pos);
    SLTNode* newnode = SLTBuyNode(x);
    newnode = pos->next;
    pos->next = newnode;
}




//删除数据



//删除pos结点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
    assert(pphead && *pphead);
    assert(pos);
    //pos为头结点时，要头删
    if (pos == *pphead)
    {
        SLPopFront(pphead);
    }
    else
    {
        SLTNode* prev = *pphead;
        while (prev->next != pos) 
        {
            prev = prev->next;
        }
        prev->next = pos->next;
        free(pos);
        pos = NULL;
    }

}


//删除pos之后的结点
void SLTEraseAfter(SLTNode* pos)
{
    assert(pos && pos->next);
    SLTNode* del = pos->next;//这里为什么要保存pos->next结点？记得看回放
    pos->next = pos->next->next;
    free(del);
    del = NULL;

}




//尾部删除数据
void SLPopBack(SLTNode** pphead)
{
    assert(pphead && *pphead); //pphead意味着传的参数不为空，*pphead表示链表不为空
    //处理只有一个结点的情况：要删除的就是头结点
    if ((*pphead)->next == NULL)
    {
        free(*pphead);
        *pphead = NULL;
    }
    else
    {
        //找尾结点的前一个prev和尾结点ptail  
        SLTNode* prev = NULL;
        SLTNode* ptail = *pphead;
        while (ptail->next)
        {
            prev = ptail;
            ptail = ptail->next;
        }
        prev->next = NULL;
        free(ptail);
        ptail = NULL;
    }
}



//头部删除数据
void SLPopFront(SLTNode** pphead)
{
    assert(pphead && *pphead);
    SLTNode* next = (*pphead)->next;
    free(*pphead);
    *pphead = next;
}


//销毁链表
void SListDestroy(SLTNode** pphead)
{
    assert(pphead && *pphead);
    SLTNode* pcur = *pphead;
    while (pcur)
    {
        SLTNode* next = pcur->next;
        free(pcur);
        pcur = next;
    }
    *pphead = NULL;

}



//查找数据
SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{
    assert(phead);
    SLTNode* pcur = phead;
    while (pcur)
    {
        if (pcur->data == x)
        {
            return pcur;
        }
        pcur = pcur->next;
    }
    //没有找到
    return NULL;

}